package com.note.back.controller;

import com.note.back.pojo.Result;
import com.note.back.pojo.SMS;
import com.note.back.pojo.User;
import com.note.back.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Map;


@RestController
@RequestMapping("/user")
@Validated
public class UserController {
    @Autowired
    UserService userService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    // 设置加密迭代次数
    private static final int times = 2;
    // 设置加密算法为 MD5
    private static final String algorithm = "md5";

    @PostMapping("/register")
    public Result register(@RequestBody Map<String,String> params){
        //一、校验参数
        String username = params.get("username");
        String password = params.get("password");
        String rePassword = params.get("rePassword");
        String email = params.get("email");
        String smsCode = params.get("smsCode");

        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password) || !StringUtils.hasLength(rePassword) || !StringUtils.hasLength(email) || !StringUtils.hasLength(smsCode)){
            return Result.error("缺少必要的参数");
        }
        //数据是否正确：1、两次密码是否一致 2、用户是否已经存在 3、验证码是否正确
        //1、两次密码是否一致
        if(!password.equals(rePassword)){
            return Result.error("两次填写的密码不一样");
        }

        //2、用户是否已经存在
        User u = userService.findByAccount(username);
        if(u!=null){
            return Result.error("用户名已被占用");
        }

        //3、验证码是否正确
        String storedCode = redisTemplate.opsForValue().get(email);
        if (storedCode != null && storedCode.equals(smsCode)) {
            // 验证成功后删除 Redis 中的验证码
            redisTemplate.delete(email);
        } else {
            return Result.error("验证码验证失败");
        }

        //二、调用service完成注册
        //1、对密码进行加密处理
        // 生成一个随机盐值
        String salt = new SecureRandomNumberGenerator().nextBytes().toString();
        // 使用 SimpleHash 类对密码进行加密，结合盐值和迭代次数
        String pwdAfterHash = new SimpleHash(algorithm,password,salt,times).toString();
        //2、进行注册
        userService.register(username, pwdAfterHash, salt, email);
        return Result.success("注册成功");
    }

    @PostMapping("/login")
    public Result<UsernamePasswordToken> login(@RequestBody User user){
        //根据用户名查询用户
        User loginUser = userService.findByAccount(user.getAccount());
        //判断该用户是否存在
        if(loginUser==null){
            return Result.error("用户不存在");
        }
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(loginUser.getAccount(), user.getPassword());
        try{
            subject.login(usernamePasswordToken);
            return Result.success(usernamePasswordToken,"登陆成功");
        }catch (AuthenticationException e){
            return Result.error("登录异常");
        }
    }

    @PostMapping("/smsCode")
    public Result smsCode(@RequestBody SMS sms){
        //根据用户名查询用户
        User loginUser = userService.findByUserEmail(sms.getEmail());
        //判断该用户是否存在
        if(loginUser==null){
            return Result.error("用户不存在");
        }
        String storedCode = redisTemplate.opsForValue().get(sms.getEmail());
        if (storedCode != null && storedCode.equals(sms.getSmsCode())) {
            // 验证成功后删除 Redis 中的验证码
            redisTemplate.delete(sms.getEmail());
            // 记录登录状态
            Subject subject = SecurityUtils.getSubject();
            User u = userService.findByUserEmail(sms.getEmail());
            UsernamePasswordToken token = new UsernamePasswordToken(u.getAccount(), u.getPassword());
            try {
                subject.login(token);
                return Result.success("登录成功");
            } catch (Exception e) {
                return Result.error("登录状态记录失败");
            }
        } else {
            return Result.error("验证码验证失败");
        }
    }

    @PostMapping("/forgotPassword")
    public Result forgotPassword(@RequestBody Map<String,String> params){
        //一、校验参数
        String username = params.get("username");
        String newPassword = params.get("newPassword");
        String reNewPassword = params.get("reNewPassword");
        String email = params.get("email");
        String smsCode = params.get("smsCode");
        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(newPassword) || !StringUtils.hasLength(reNewPassword) || !StringUtils.hasLength(email) || !StringUtils.hasLength(smsCode)){
            return Result.error("缺少必要的参数");
        }
        //数据是否正确：1、两次密码是否一致 2、用户是否已经存在 3、验证码是否正确
        //1、两次密码是否一致
        if(!newPassword.equals(reNewPassword)){
            return Result.error("两次填写的密码不一样");
        }

        //2、用户是否存在
        User u = userService.findByAccount(username);
        if(u==null){
            return Result.error("用户不存在");
        }

        //3、验证码是否正确
        if(!email.equals(u.getEmail())){
            return Result.error("填写的邮箱号码不是验证邮箱");
        }
        String storedCode = redisTemplate.opsForValue().get(email);
        if (storedCode != null && storedCode.equals(smsCode)) {
            // 验证成功后删除 Redis 中的验证码
            redisTemplate.delete(email);
        } else {
            return Result.error("验证码验证失败");
        }

        //二、调用service完成密码更新
        // 使用 SimpleHash 类对密码进行加密，结合盐值和迭代次数
        String pwdAfterHash = new SimpleHash(algorithm,newPassword,u.getSalt(),times).toString();
        userService.forgotPassword(u.getId(),pwdAfterHash);
        return Result.success("密码设置成功");
    }

    @GetMapping("/userInfo")
    public Result<User> userInfo(){
        Subject subject = SecurityUtils.getSubject();
        User u = (User)subject.getPrincipal();
        if(u==null){
            return Result.error("用户未登录");
        }
        String account = u.getAccount();
        User user = userService.findByAccount(account);
        user.setPassword("");
        return Result.success(user,"用户信息获取成功");
    }

    @PostMapping("/update")
    public Result update(@RequestBody @Validated User user){
        userService.update(user);
        return Result.success("用户信息更新成功");
    }

    @PostMapping("/changeCode")
    public Result updatePwd(@RequestBody Map<String,String> params){
        //1、校验参数
        String oldPassword = params.get("oldPassword");
        String newPassword = params.get("newPassword");
        String reNewPassword = params.get("reNewPassword");
        if(!StringUtils.hasLength(oldPassword) || !StringUtils.hasLength(newPassword) || !StringUtils.hasLength(reNewPassword)){
            return Result.error("缺少必要的参数！！！");
        }
        //原密码是否正确
        Subject subject = SecurityUtils.getSubject();
        User u = (User)subject.getPrincipal();
        User loginUser = userService.findByAccount(u.getAccount());
        if(!loginUser.getPassword().equals(new SimpleHash(algorithm,oldPassword,loginUser.getSalt(),times).toString())){
            return Result.error("原密码错误！！！");
        }
        if(!newPassword.equals(reNewPassword)){
            return Result.error("两次填写的新密码不一样！！！");
        }
        //2、调用service完成密码更新

        userService.updatePwd(loginUser.getId(),new SimpleHash(algorithm,newPassword,loginUser.getSalt(),times).toString());
        return Result.success("密码修改成功");
    }

    @GetMapping("/logout")
    public Result logout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return Result.success("登出成功");
    }
}
